﻿using System;
using BSDS.Core.Data.Local;
using BSDS.Core.Model.Services;
using BSDS.Core.Model.Services.Jobs;

namespace BSDS.Commands.Commands.Implementation
{
    public class DownloadCommand : CommandBase
    {
        private readonly DownloadService downloadService;
        private readonly DownloadCommandConfiguration configuration;
        private readonly JobService jobService;
        private readonly JobRepository jobRepository;
        private readonly DataRepository dataRepository;

        public DownloadCommand(DownloadService downloadService, DownloadCommandConfiguration configuration,
             JobService jobService, JobRepository jobRepository, DataRepository dataRepository)
        {
            this.downloadService = downloadService;
            this.configuration = configuration;
            this.jobService = jobService;
            this.jobRepository = jobRepository;
            this.dataRepository = dataRepository;
        }

        public override CommandResult Execute(ExecutionContext context)
        {
            DownloadJob job;

            if (configuration.ResumeCompletedJob)
            {
                job = jobRepository.Get<DownloadJob>(configuration.ResumedJobId);
            }
            else
            {
                job = downloadService.ScheduleDownload(configuration.DataSourceName, configuration.Format,
                                                       configuration.OutFile, configuration.Portal);

                job.Command = context.CommandInfo.ToString();
                jobRepository.Save(job);

                jobService.WaitForEnd(job.Id, downloadService);
            }

            var data = downloadService.DownloadResults(job);

            if (!dataRepository.CanBeSaved(data, configuration.Format))
            {
                const string message = "Dataset contains {0}. Please use /format=tab or /format=xml";

                throw new ArgumentException(string.Format(message, configuration.Format.Value));
            }

            data.FixMatchedMethod();

            if (configuration.Portal)
            {
                if (configuration.Format != DataFormat.Tab && configuration.Format != DataFormat.Pipe)
                {
                    throw new ArgumentException("/portal option can be used only with /format=tab or /format=pipe");
                }

                dataRepository.SaveInPortalFormat(data, configuration.OutFile, configuration.Format);
            }
            else
            {
                dataRepository.SaveToFile(data, configuration.OutFile, configuration.Format);
            }

            return CommandResult.Success();
        }
    }

    public class DownloadCommandConfiguration
    {
        public string DataSourceName { get; private set; }
        public DataFormat Format { get; private set; }
        public string OutFile { get; set; }
        public bool Portal { get; private set; }
        public bool ResumeCompletedJob { get; private set; }
        public string ResumedJobId { get; private set; }

        public DownloadCommandConfiguration(string dataSourceName, DataFormat format, string outFile, bool portal,
            bool resumeCompletedJob, string resumedJobId)
        {
            DataSourceName = dataSourceName;
            Format = format;
            OutFile = outFile;
            Portal = portal;
            ResumeCompletedJob = resumeCompletedJob;
            ResumedJobId = resumedJobId;
        }
    }
}